//https://www.bilibili.com/video/BV1GP411R7Y4/?spm_id_from=333.788&vd_source=16b267e92edd288778342448b69d98f9

#include <iostream>
#include <string>
#include <vector>

// 1.抽象产品类
class AbstractProduct
{   
    public:
    virtual void SetDisplayer(std::string displayer)       = 0;
    virtual void SetMouse(std::string mouse)               = 0;
    virtual void SetKeyboard(std::string keyboard)         = 0;
    virtual void SetHost(std::string host)                 = 0;
    virtual void show() const                              = 0;
};

// 2.具体产品类
class Computer : public AbstractProduct{
public: 
     void SetDisplayer(std::string displayer){
        m_list.push_back(displayer);
     }      
     void SetMouse(std::string mouse){
        m_list.push_back(mouse);
     }                
     void SetKeyboard(std::string keyboard){
        m_list.push_back(keyboard);
     }             
     void SetHost(std::string host){
        m_list.push_back(host);
     }                 

    void show() const{
        std::cout << "电脑配置结果： " << std::endl;
        for(auto& v: m_list){
            std::cout << v << std::endl;
        }
    }
    std::vector<std::string> m_list;
};

// 3.抽象建造者
class AbstractBuilder{
public:
    AbstractBuilder(): product(new Computer){}

    virtual void BuildDisplayer(std::string displayer)       = 0;
    virtual void BuildMouse(std::string mouse)               = 0;
    virtual void BuildKeyboard(std::string keyboard)         = 0;
    virtual void BuildHost(std::string host)                 = 0;
    AbstractProduct* GetProduct(){
        return product;
    }
protected:
    AbstractProduct* product;

};


// 4.具体建造者--->组装电脑的技术员
class ConcreteBuilder : public AbstractBuilder{
public:
     void BuildDisplayer(std::string displayer){
        product->SetDisplayer(displayer);
     }
     void BuildMouse(std::string mouse){
        product->SetMouse(mouse);
     }        
     void BuildKeyboard(std::string keyboard){
        product->SetKeyboard(keyboard);
     }          
     void BuildHost(std::string host) {
        product->SetHost(host);
        
     }                 
};

// 5.指挥者类
class Director{
public:
    Director(AbstractBuilder* pBuilder): pBuilder(pBuilder){}
    AbstractProduct* createProduct(std::string displayer,std::string mouse,
                                    std::string keyboard,std::string host){
                                        pBuilder->BuildDisplayer(displayer);
                                        pBuilder->BuildHost(host);
                                        pBuilder->BuildMouse(mouse);
                                        pBuilder->BuildKeyboard(keyboard);
                                        return  pBuilder->GetProduct();
                                    }
private:
    AbstractBuilder* pBuilder;
};

int main(){
    AbstractBuilder*pB = new ConcreteBuilder;
    Director* pD = new Director(pB);
    AbstractProduct* computer = pD->createProduct("罗技显示器", "雷蛇鼠标", "测试键盘", "ROG主机");
    computer->show();
    return 0;
}